--[[
    master网关
    统筹控制子网关
]]

local skynet = require "skynet"
require "skynet.manager"
local Service = require "core.Service"
local Socket = require "skynet.socket"
local SocketDriver = require "skynet.socketdriver"
local ServiceName = require "enum.ServiceName"

local maxclient
local clientNumber = 0
local protocol
local gatecount
local balance = 1

---@type table<number, Gate>
local slaves = {}

-- fd => true
---@type table<number, boolean>
local fds = {}

---@class GateMaster
local M = {}
function M.close(fd)
    if fds[fd] then
        clientNumber = clientNumber - 1
        fds[fd] = nil
    end
end

function M.start(conf)
    gatecount = conf.gatecount or 8
    maxclient = conf.maxclient or 1024
    protocol = conf.protocol or "ws"

    local master = skynet.self()
    for i = 1, gatecount do
        local s = Service:new(skynet.new_hotservice("service/Gate"))
        slaves[i] = s
        s:start({
            master = master,
            protocol = protocol
        })
    end

    local playerMgr = Service:new(skynet.new_hotservice("service/PlayerMgr"))
    playerMgr:start(table.column(slaves, "address"))

    local server = Socket.listen(conf.host, conf.port)
    Socket.start(server, function(fd, addr)
        if clientNumber > maxclient then
            SocketDriver.close(fd)
            return
        end

        clientNumber = clientNumber + 1

        local s = slaves[balance]
        balance = balance + 1
        fds[fd] = true
        if balance > gatecount then
            balance = 1
        end

        s.accept(fd, addr)
    end)
end

function M.init()
    skynet.dispatch_lua(M)
    skynet.register(ServiceName.GATE_MASTER)
end

return M